package com.stars.module.router.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stars.base.constants.CommonNumberConstants;
import com.stars.base.constants.RedisConstants;
import com.stars.base.entity.CommonDTO;
import com.stars.base.entity.Result;
import com.stars.base.entity.SessionUser;
import com.stars.base.entity.TreeNode;
import com.stars.module.router.entity.StarRouter;
import com.stars.module.router.entity.StarRouterVo;
import com.stars.module.router.mapper.RouterMapper;
import com.stars.module.router.service.RouterService;
import com.stars.util.cache.CacheUtil;
import com.stars.util.common.DevelopKit;
import com.stars.util.tree.TreeNodeUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author : moon
 * @version : 1.0
 * @date : 2023/7/31
 * @description : 动态路由
 */
@Service
public class RouterServiceImpl implements RouterService {

    private final RouterMapper routerMapper;

    private final CacheUtil cacheUtil;

    public RouterServiceImpl(RouterMapper routerMapper, CacheUtil cacheUtil) {
        this.routerMapper = routerMapper;
        this.cacheUtil = cacheUtil;
    }

    @Override
    public JSONArray loadTree() {

        JSONArray array = new JSONArray();

        LambdaQueryWrapper<StarRouter> query = new LambdaQueryWrapper<>();
        query.orderByAsc(StarRouter::getShowOrder);

        List<StarRouter> list = routerMapper.selectList(query);

        List<TreeNode> treeNodes = new ArrayList<>();

        for(StarRouter router : list) {
            TreeNode node = new TreeNode();

            node.setValue(router.getId());
            node.setLabel(router.getTitle());
            node.setpId(router.getFid());

            JSONObject attr = new JSONObject();
            attr.put("path",router.getPath());
            node.setAttr(attr);

            treeNodes.add(node);
        }

        TreeNode root = new TreeNode(CommonNumberConstants.ZERO_STR,"路由管理",CommonNumberConstants.MINUS_ONE_STR);

        array.add(TreeNodeUtil.merge(root,treeNodes).toJSON());

        return array;
    }

    @Override
    public JSONObject loadListByFid(CommonDTO dto) {
        Page<StarRouter> page = Page.of(dto.getCurrent(),dto.getPageSize());

        LambdaQueryWrapper<StarRouter> query = new LambdaQueryWrapper<>();

        query.eq(StarRouter::getFid,dto.getFid()).like(StarRouter::getPath,dto.getSearch());
        query.orderByAsc(StarRouter::getShowOrder);

        Page<StarRouter> routerPage = routerMapper.selectPage(page, query);

        JSONObject result = new JSONObject();

        result.put("list",routerPage.getRecords());
        result.put("total",routerPage.getTotal());

        return result;
    }

    @Override
    public Result removeData(String id) {
        return Result.result(routerMapper.deleteById(id) > 0,null,"删除失败！");
    }

    @Override
    public StarRouter loadDataById(String id) {
        return routerMapper.selectById(id);
    }

    @Override
    public boolean saveOrUpdateData(StarRouter router) {

        if(StringUtils.hasLength(router.getId())){
            return routerMapper.updateById(router) > 0;
        }
        router.setId(DevelopKit.generateUUID());
        DevelopKit.setBaseInfo(router);

        return routerMapper.insert(router) > 0;
    }

    /**
     * 获取动态路由信息，###需要关联菜单，根据权限加载路由，缓存redis
     * TODO 路由设置需不需要权限，没登陆返回没有加权限的。暂时都加载，待优化，404不加权限
     * @author : moon
     * @date :  2023/9/5 12:11
     * @return: java.util.List<com.stars.module.router.entity.StarRouterVo>
     */
    @Override
    public List<StarRouterVo> getUserRouter() {

        SessionUser user = DevelopKit.getSessionUser();
        String key;
        if(user != null){
            key = RedisConstants.ROUTER_PREFIX + user.getUserId();
        }else {
            key = RedisConstants.ROUTER_PREFIX + "public";
        }

        Object obj = cacheUtil.getValue(false, key);

        if(obj != null){
            return DevelopKit.castObj2List(obj, StarRouterVo.class);
        }

        LambdaQueryWrapper<StarRouter> query = new LambdaQueryWrapper<>();

        List<StarRouter> routerList = routerMapper.selectList(query);

        Map<String,StarRouterVo> map = new HashMap<>();

        // 根0
        StarRouterVo vo = new StarRouterVo();
        vo.setId(CommonNumberConstants.ZERO_STR);
        map.put(vo.getId(), vo);

        for(StarRouter starRouter : routerList){

            vo = new StarRouterVo();

            BeanUtils.copyProperties(starRouter,vo);

            map.put(starRouter.getId(), vo);
        }

        processTree(map, CommonNumberConstants.ZERO_STR);

        List<StarRouterVo> list = map.get(CommonNumberConstants.ZERO_STR).getChildren();

        cacheUtil.setValue(false, key, list);

        return list;
    }

    private void processTree(Map<String, StarRouterVo> map, String rootId) {

        if(map.containsKey(rootId)){
            for(String key: map.keySet()){
                String fid = map.get(key).getFid();
                if(rootId.equals(fid)){
                    processTree(map,key);
                    map.get(rootId).getChildren().add(map.get(key));
                }
            }
        }
    }
}
